package com.zhihu.ws;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zhihu.client.UserClient;
import com.zhihu.dao.ChatRepository;
import com.zhihu.pojo.Chat;
import com.zhihu.pojo.User;
import com.zhihu.pojo.baseVo.BaseResult;
import com.zhihu.service.ChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Component
@ServerEndpoint("/chat/{userId}")
public class ChatEndpoint {

    //用来存储每一个客户端对象对应的ChatEndpoint对象
    private static Map<String,ChatEndpoint> onlineUsers = new ConcurrentHashMap<>();

    //声明Session对象，通过该对象可以发送消息给指定用户
    private Session session;

    //用户信息
    private User user;
    //存放离线消息
    private static ConcurrentMap<String, Map<String, List<Object>>> messageMap=new ConcurrentHashMap<>();

    @Autowired
    ChatService chatService;

    @Autowired
    UserClient userClient;

    @Autowired
    ChatRepository chatRepository;

    @OnOpen
    //连接建立时被调用
    public void onOpen(Session session,@PathParam("userId") String userId){
        //1、调用user服务，获取当前用户信息
        BaseResult userById = userClient.findUserById(Integer.valueOf(userId));
        this.session = session;
        this.user = (User) userById.getData();
        //判断集合中是否存在当前用户id
        if(onlineUsers.containsKey(userId)){
            //存在则删除后加入列表
            onlineUsers.remove(userId);
            onlineUsers.put(userId,this);
        }else{
            //不存在直接加入
            onlineUsers.put(userId,this);
        }
        if(messageMap.get(userId)!=null){
            //说明在用户没有登录的时候有人给用户发送消息
            //该用户所有未收的消息
            Map<String, List<Object>> lists=messageMap.get(userId);
            //对象用户发送的离线消息
            Iterator iteratorGet = lists.keySet().iterator();
            while (iteratorGet.hasNext()) {
                String keys = (String) iteratorGet.next();//键
                List<Object> list = lists.get(keys);
                if(list!=null){
                    for(int i=0;i<list.size();i++) {
                        //封装消息类型   消息内容+"["+发送消息的人+";"+接收消息的人","+0
                        JSONObject rs = new JSONObject();
                        rs.put("message", list.get(i));
                        rs.put("from", keys);
                        rs.put("to", userId);
                        //message=list.get(i)+"["+keys+";"+username+","+0;
                        onMessage(session,rs.toString());
                    }
                }
                iteratorGet.remove();
            }
        }
    }

    @OnMessage
    //接收到客户端发送的数据时调用
    public void onMessage(Session session,String message){
        //转成json对象
        JSONObject jsonObject = JSON.parseObject(message);
        //获取对应的信息
        String textMessage = jsonObject.getString("message");
        String fromUserId = jsonObject.getString("from");
        String toUserId = jsonObject.getString("to");
        //封装到map集合中
        Map<String,Object> map1 = new HashMap<>();
        map1.put("textMessage",textMessage);
        map1.put("fromUserId",fromUserId);
        //判断是否发送给所有人
        if (toUserId.equals("All")){
            map1.put("toUserId","所有人");
            sendMessageAll(JSON.toJSONString(map1));
        }else {
            //判断用户是否在线
            if (onlineUsers.get(toUserId)!=null){
                map1.put("toUserId",toUserId);
                sendMessageTo(JSON.toJSONString(map1),toUserId);
                insertChat(toUserId,fromUserId,textMessage,2);
                System.out.println("信息已转发");
            }else {
                saveMessage(toUserId,fromUserId,textMessage);
                insertChat(toUserId,fromUserId,textMessage,1);
                System.out.println("信息已保存到数据库");
            }
        }


    }

    @OnClose
    //连接关闭时调用
    public void onClose(){
        onlineUsers.remove(user.getUserId().toString());
        System.out.println("用户"+user.getUserName()+"断开连接");
    }

    @OnError
    //服务端发生错误时调用
    public void onError(Throwable error) {
        System.out.println("服务端发生了错误"+error.getMessage());
    }

    //发送消息给所有人
    private void sendMessageAll(String message){
        //获取所有用户
        List<User> allUsers = userClient.findAllUsers();
        //遍历
        for (User u: allUsers) {
            Integer toUserId = u.getUserId();
            //排除当前用户，只给其他用户发送
            if (!toUserId.equals(user.getUserId())) {
              //判断用户是否在线
              if (onlineUsers.keySet().contains(toUserId.toString())){
                  //在线执行转发消息的方法
                  sendMessageTo(message,toUserId.toString());
              }else {
                  //不在线执行存储离线消息的方法
                  saveMessage(toUserId.toString(),user.getUserId().toString(),message);
              }
          }
        }
    }

    //转发个人消息
    private void sendMessageTo(String message, String toUserId){
        try {
            //获取收信人用户的chatEndpoint实例
            ChatEndpoint chatEndpoint = onlineUsers.get(toUserId);
            chatEndpoint.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //收信人不在线，储存离线消息
    private void saveMessage(String toUserId,String fromUserId,String textMessage) {
        if(messageMap.get(toUserId)==null) {
            //用户不在线时 第一次给他发消息
            Map<String, List<Object>> maps=new HashMap<>();//该用户的所有消息
            List<Object> list=new ArrayList<>();//该用户发的离线消息的集合
            list.add(textMessage);
            maps.put(fromUserId, list);
            messageMap.put(toUserId, maps);
        }else {
            //不在线再次发送消息
            //second 给用户的所有消息
            Map<String,List<Object>> listObject=messageMap.get(toUserId);
            List<Object> objects=new ArrayList<>();
            if(listObject.get(fromUserId)!=null) {//这个用户给收消息的这个用户发过消息
                //此用户给该用户发送过离线消息（此用户给该用户发过的所有消息）
                objects=listObject.get(fromUserId);
                objects.add(textMessage);//加上这次发送的消息
                //替换原来的map
                listObject.put(fromUserId, objects);
            }else {//这个用户没给该用户发送过离线消息
                objects.add(textMessage);
                listObject.put(fromUserId, objects);
            }
        }
    }

    //将信息储存到数据库
    private void insertChat(String toUserId,String fromUserId,String textMessage,Integer status){
        //通过id分别查询发信人和收信人的信息
        User fromUser = (User)userClient.findUserById(Integer.valueOf(fromUserId)).getData();
        User toUser = (User)userClient.findUserById(Integer.valueOf(toUserId)).getData();
        //生成消息实例
        Chat chat = new Chat(null,fromUser.getImg(),fromUser.getUserName(),fromUser.getUserId(),
                textMessage,new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),
                toUser.getImg(),toUser.getUserName(),toUser.getUserId(),1,status);
        //将该chat对象保存到数据库中
        chatService.insertChat(chat);

    }

}
